﻿using Idea.Entity;
using Idea.Query.Interface;
using Idea.Repository.Interface;
using Idea.UnitOfWork.Interface;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;

namespace Idea.Repository
{
    /// <summary>
    /// Default implementation of generic repository
    /// </summary>
    /// <typeparam name="TEntity">Entity type for repository</typeparam>
    /// <typeparam name="TKey">Primary key type for entity</typeparam>
    public class Repository<TEntity, TKey> : IRepository<TEntity, TKey>
        where TEntity : Entity<TKey>
    {
        private IUnitOfWorkManager _manager;

        protected System.Data.Entity.DbContext context;
        protected DbSet<TEntity> database;

        public IUnitOfWorkManager Manager
        {
            get
            {
                return _manager;
            }
            set
            {
                _manager = value;
            }
        }

        public long Count(IQueryObject<TEntity> query)
        {
            ResolveUnitOfWork();
            return query.Count(database.AsQueryable());
        }

        public IEnumerable<TEntity> Fetch(IQueryObject<TEntity> query)
        {
            ResolveUnitOfWork();
            return query.Fetch(database.AsQueryable());
        }

        public TEntity FetchOne(IQueryObject<TEntity> query)
        {
            ResolveUnitOfWork();
            return query.FetchOne(database.AsQueryable());
        }

        public TEntity Find(TKey id)
        {
            ResolveUnitOfWork();
            return database.Find(id);
        }

        public TEntity Create(TEntity entity)
        {
            ResolveUnitOfWork();
            return database.Add(entity);
        }

        public TEntity Update(TEntity entity)
        {
            ResolveUnitOfWork();
            database.Attach(entity);
            context.Entry(entity).State = EntityState.Modified;
            return entity;
        }

        public void Delete(TEntity entity)
        {
            ResolveUnitOfWork();
            database.Remove(entity);
        }



        public IUnitOfWork ResolveUnitOfWork()
        {
            IUnitOfWork uow = _manager.GetCurrentUnitOfWork();
            context = uow.DbContext;
            database = context.Set<TEntity>();
            
            return uow;
        }
    }
}
